package com.yeban.javase.day19.test.test3;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Desc TODO
 * @Author yeban
 * @Date 2025/11/3
 */
public class ThreadPoolTCPServer {

    public static void main(String[] args) {
        // 创建自定义线程池
        ThreadPoolExecutor pool = new ThreadPoolExecutor(
                2, 3,
                60L, TimeUnit.SECONDS,
                new LinkedBlockingDeque<Runnable>(3)
        );
        System.out.println("---------- TCPServer ----------");

        // 启动服务端
        try(ServerSocket ss = new ServerSocket(8123)) {
            // 等待接入客户端
            Socket socket = ss.accept();
            System.out.println("成功接入客户端：" + socket.getRemoteSocketAddress());

            // 同时启动收/发线程
            pool.execute(new ServerReader(socket));
            pool.execute(new ServerWriter(socket));
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            // 关闭线程池
            pool.shutdown();
        }
    }
}

/**
 * 读线程：用来持续监听客户端发来的消息
 */
class ServerReader implements Runnable {
    private final Socket socket;

    ServerReader(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        // 创建BufferedReader，目的将客户端发来的inputStream流接收
        try(BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));) {
            // 创建一个String来接收
            String msg = null;
            // 持续监听
            while((msg = br.readLine()) != null) {
                // 如果客户端输入exit，说明客户端退出
                if(msg.equals("exit")) {
                    System.out.println(socket.getRemoteSocketAddress() + "退出聊天~");
                    break;
                } else {
                    System.out.println(socket.getRemoteSocketAddress() + "说：" + msg);
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                socket.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

/**
 * 写线程：用来持续写出消息给客户端
 */
class ServerWriter implements Runnable {

    private final Socket socket;

    ServerWriter(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try(PrintWriter pw = new PrintWriter(socket.getOutputStream());) {
            Scanner sc = new Scanner(System.in);
            while(true) {
                String msg = sc.nextLine();
                if(msg.equals("exit")) {
                    System.out.println("服务器主动下线~");
                    break;
                }
                // 写消息
                pw.println(msg);
                pw.flush();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                socket.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
